import store from '@/store';
import { Toast } from 'antd-mobile';
import axios from 'axios';
import history from './history';
import { getAuth, getToken, setToken } from './storage';

// 请求基地址
export const baseURL = 'http://geek.itheima.net';

// 创建 axios 实例
const request = axios.create({
  baseURL: baseURL,
  timeout: 5000,
});

// 请求拦截器
request.interceptors.request.use(
  function (config) {
    if (getToken()) {
      // 断言 最后的类型可以为any
      (config.headers as any).Authorization = 'Bearer ' + getToken();
    }
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  function (response) {
    return response.data;
  },
  async function (error) {
    // 情况1： 断网时，我们要提示用户断网了，网络有问题
    if (!error.response) {
      Toast.show({ content: '网络有问题，请检查网络', duration: 1000 });
      return Promise.reject(error);
    }
    // 情况2： 断网时，我们要提示用户断网了，网络有问题
    if (error.response.status !== 401) {
      Toast.show({ content: error.response.data.message, duration: 1000 });
      return Promise.reject(error);
    }

    //无感刷新的效果：
    // 1. token 与refresh_token,都是token
    //作用：
    // 1.token是用来请求业务数据的token,时效性比较短
    // 2.refresh_token 是请求token的token,时效性比较短。只有一个作用：请求新的token,不能请求业务数据

    /* 401状态分两种情况 
      1 无token  2 有token不存在refresh_token  3 有token（可能过期）也有refresh_token
    */
    const { token, refresh_token } = getAuth();
    // 1 无toke  这条情况可以删除，当是401时token判断意义不大
    if (!token) {
      history.push('/login');
      Toast.show({ content: '登录超时，重新登录' });
      return Promise.reject(error);
    }
    // 2 有token不存在refresh_token
    if (!refresh_token) {
      history.push('/login');
      Toast.show({ content: '登录超时，重新登录' });
      return Promise.reject(error);
    }

    // 3 有token（可能过期）也有refresh_token
    try {
      // 可以通过refresh_token获取新的token 发起独立的axios请求（防止会获取修的token）
      const res = await axios(baseURL + '/v1_0/authorizations', {
        method: 'put',
        headers: { Authorization: 'Bearer ' + refresh_token },
      });
      // console.dir(error);

      const auth = {
        token: res.data.data.token,
        refresh_token,
      };
      // 把新的token保存到本地和redux中
      setToken(auth);
      store.dispatch({ type: 'user/login', payload: auth });
      // 发起之前的失败的请求，返回结果
      return request(error.config);
    } catch (error) {
      // refresh_token存在但过期的情况捕获
      history.push('/login');
      Toast.show({ content: '登录超时，重新登录' });
      return Promise.reject(error);
    }
  }
);

// 导出 axios 实例
export default request;
